package ar.edu.unrn.lia.bean;

import java.io.Serializable;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.persistence.OptimisticLockException;
import javax.persistence.PersistenceException;

import org.primefaces.event.SelectEvent;
import org.primefaces.event.map.PointSelectEvent;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.map.DefaultMapModel;
import org.primefaces.model.map.LatLng;
import org.primefaces.model.map.MapModel;
import org.primefaces.model.map.Marker;

import ar.edu.unrn.lia.bean.datamodel.LazyPropiedadDataModel;
import ar.edu.unrn.lia.bean.filter.PropiedadFiltro;
import ar.edu.unrn.lia.model.Ciudad;
import ar.edu.unrn.lia.model.Coordenada;
import ar.edu.unrn.lia.model.Propiedad;
import ar.edu.unrn.lia.model.PuntoInteres;
import ar.edu.unrn.lia.model.Propiedad.AlquilerVenta;
import ar.edu.unrn.lia.model.PropiedadTipo;
import ar.edu.unrn.lia.model.Propietario;
import ar.edu.unrn.lia.service.CiudadService;
import ar.edu.unrn.lia.service.PropiedadService;
import ar.edu.unrn.lia.service.PropiedadTipoService;
import ar.edu.unrn.lia.service.PropietarioService;

@ManagedBean(name = "propiedadBean")
@ViewScoped
public class PropiedadBean extends GenericBean<Propiedad> implements
		Serializable {

	private static final long serialVersionUID = 1L;

	private PropiedadFiltro filtros = new PropiedadFiltro();

	private Coordenada coordenadas = UtilsBean.LATLONG;

	private MapModel mapaModel = new DefaultMapModel();

	@ManagedProperty(value = "#{propiedadService}")
	PropiedadService entityService;

	@ManagedProperty(value = "#{propietarioService}")
	PropietarioService propietarioService;

	@ManagedProperty(value = "#{ciudadService}")
	CiudadService ciudadService;

	@ManagedProperty(value = "#{propiedadTipoService}")
	PropiedadTipoService propiedadTipoService;

	public String create() {
		setEntity(new Propiedad());
		return REDIRECT_CREATE;
	}

	// TODO http://primefaces.org/showcase/ui/gmapAddMarkers.jsf AddMarker
	// http://primefaces.org/showcase/ui/gmapDraggableMarkers.jsf Drag
	public void inicio() {
		if (!FacesContext.getCurrentInstance().isPostback()) {
			if (getId() != null) {
				setEntity(entityService.getEntityById(getId()));
				setCoordenadas(getEntity().getCoordenada());
				
				for (PuntoInteres p : getEntity().getBarrio().getPuntosInteres()) {
					getMapaModel().addOverlay(new Marker(new LatLng(p
							.getCoordenada().getLat(), p.getCoordenada().getLng()),
							p.getDescripcion(), p.getId().toString(), FacesContext.getCurrentInstance()
							.getExternalContext().getRequestContextPath()
							+ "/resources/images/"+ p.getTipo().toString() + ".png"));					
				}
				
				// Agrego las coordenadas actuales de la Propiedad si esta
				// seteado
				// if (getEntity().getCoordenada() != null) {
				// Marker marker = new Marker(new LatLng(getEntity()
				// .getCoordenada().getLat(), getEntity()
				// .getCoordenada().getLng()), getEntity()
				// .direccionCompleta(), getEntity().getId()
				// .toString(), FacesContext.getCurrentInstance()
				// .getExternalContext().getRequestContextPath()
				// + "/resources/images/gmap-icon-disponible.png"
				//
				// );
				//
				// this.mapaModel.addOverlay(marker);
				// }

			} else {
				setEntity(new Propiedad());
			}
		}
	}

	public void onRowSelect(SelectEvent event) {
		agregarMensaje(FacesMessage.SEVERITY_INFO, "Propiedad Seleccionada: ",
				((Propiedad) event.getObject()).direccionCompleta());
	}

	public String update() {
		try {
			if (getEntity().getId() == null) {
				entityService.save(getEntity());
				mensajeFlash("Crear Propiedad",
						"Operación realizada con exito.");
			} else {
				entityService.update(getEntity());
				mensajeFlash("Modificar Propiedad",
						"Operación realizada con exito.");
			}
			return REDIRECT_SEARCH;
		} catch (OptimisticLockException e) {
			agregarMensaje(FacesMessage.SEVERITY_ERROR, "Bloqueo",
					"Alquien modificó esta Propiedad, reconsulte.");
			return null;
		} catch (Exception e) {
			agregarMensaje(FacesMessage.SEVERITY_ERROR, "Error", e.getMessage());
			return null;
		}
	}

	public String delete(Propiedad entity) {
		try {
			entityService.delete(entity);
			mensajeFlash("Eliminar Propiedad", "Operación realizada con exito.");
			return REDIRECT_SEARCH;
		} catch (OptimisticLockException e) {
			agregarMensaje(FacesMessage.SEVERITY_ERROR, "Bloqueo",
					"Alquien modificó esta Propiedad, reconsulte.");
			return null;
		} catch (PersistenceException e) {
			agregarMensaje(FacesMessage.SEVERITY_ERROR, "Eliminar Propiedad",
					"No se puede eliminar, la propiedad esta asociada a un Alquiler.");
			return null;
		} catch (Exception e) {
			agregarMensaje(FacesMessage.SEVERITY_ERROR, "Eliminar Propiedad",
					e.getMessage());
			return null;
		}
	}

	public LazyDataModel<Propiedad> getList() {
		if (getModelLazy() == null) {
			setModelLazy(new LazyPropiedadDataModel(entityService));
		}
		((LazyPropiedadDataModel) getModelLazy()).setFiltros(filtros);
		return getModelLazy();
	}

	public List<Propiedad> getPropiedads() {
		return entityService.getAll();
	}

	public PropiedadFiltro getFiltros() {
		return filtros;
	}

	public void setFiltros(PropiedadFiltro filtros) {
		this.filtros = filtros;
	}

	public void liampiarFiltros() {
		setFiltros(new PropiedadFiltro());
	}

	public PropiedadService getEntityService() {
		return entityService;
	}

	public void setEntityService(PropiedadService entityService) {
		this.entityService = entityService;
	}

	public PropietarioService getPropietarioService() {
		return propietarioService;
	}

	public void setPropietarioService(PropietarioService propietarioService) {
		this.propietarioService = propietarioService;
	}

	public PropiedadTipoService getPropiedadTipoService() {
		return propiedadTipoService;
	}

	public void setPropiedadTipoService(
			PropiedadTipoService propiedadTipoService) {
		this.propiedadTipoService = propiedadTipoService;
	}

	public CiudadService getCiudadService() {
		return ciudadService;
	}

	public void setCiudadService(CiudadService ciudadService) {
		this.ciudadService = ciudadService;
	}

	public void onPointSelect(PointSelectEvent event) {
		agregarMensaje(FacesMessage.SEVERITY_INFO,
				"Se agregaron las siguientes Coordenadas:", "Lat:"
						+ event.getLatLng().getLat() + ", Lon:"
						+ event.getLatLng().getLng());

	}

	public List<Propietario> propietarios(String query) {
		return getPropietarioService().findByQuery(query, "apellido", "desc");
	}

	public List<Ciudad> ciudades() {
		return getCiudadService().getAll();
	}

	public List<PropiedadTipo> propiedadTipos() {
		return getPropiedadTipoService().getAll();
	}

	public Boolean renderAlquiler() {
		if (getEntity().getTipoDisponibilidad() == null)
			return true;
		return !getEntity().getTipoDisponibilidad().equals(AlquilerVenta.VENTA);
	}

	public Boolean renderVenta() {
		if (getEntity().getTipoDisponibilidad() == null)
			return true;
		return !getEntity().getTipoDisponibilidad().equals(
				AlquilerVenta.ALQUILER);
	}

	public Coordenada getCoordenadas() {
		return coordenadas;
	}

	public void setCoordenadas(Coordenada coordenadas) {
		this.coordenadas = coordenadas;
	}

	public MapModel getMapaModel() {
		return mapaModel;
	}

	public void setMapaModel(MapModel mapaModel) {
		this.mapaModel = mapaModel;
	}
}
